require 'rubygems'
require 'open4'


rootdir = Dir.pwd

def draw_line(mark, len, label = "")
  str = ""
  if label.length > 0
    str += mark * (len/2 - label.length - 2) + " #{label} " 
  end
  str += mark * (len - str.length)
  puts str
end

task :unit_compile_test, :unit do |t, args|
  args.with_defaults(:unit => nil)
  if args[:unit] == nil
    files = Dir.new("./c_files").to_a
  else
    files = [args[:unit]]
  end
  files.each do |dir|
    if dir =~ /^\./ then next end
    draw_line(">",70,dir)
    path = File.join(rootdir,"c_files",dir,"src")
    cd path
    sh "make clean"
    sh "make"
    file = File.join(path,"compile_test")
    if not File.exists?(file) and not File.exists?(file + ".exe")
      fail "Compiling '" + dir + "' failed.  No binary '" + file + "' or '" + file + ".exe' found."
    end
    draw_line("<",70) 
  end
end

task :unit_tests, :unit, :test do |t, args|
  args.with_defaults(:unit => nil)
  if args[:unit] == nil
    files = Dir.new("./c_files").to_a
  else
    files = [args[:unit]]
  end
  cd File.join(rootdir,"UnitTestEngine")
  sh "make clean; make"
  files.each do |dir|
    if dir =~ /^\./ then next end
    if args[:test] == nil
      tests = Dir.new(File.join(rootdir,"c_files",dir,"Functions")).to_a
    else
      tests = [args[:test]]
    end
    tests.each do |test|
      if test =~ /^\./ then next end
      draw_line(">",70,dir + "/" + test)
      path = File.join(rootdir,"c_files",dir,"Functions",test)
      cd path
      sh "make clean"
      sh "make"
      if File.exists?(File.join(path,"test.rb"))
        sh "ruby test.rb"
        next
      end
      file = Array.new
      file.push File.join(path,"test")
      file.push File.join(path,"test.exe")
      file.push File.join(path,"libtest.so")
      if not File.exists?(file[0]) and not File.exists?(file[1]) and not File.exists?(file[2])
        fail "Compiling '" + dir + "/" + test + "' failed.  No binary '" + file[0] + "' or '" + file[1] + "' or '" + file[2] + "'  found."
      end
      draw_line("<",70)
      if File.exists?(file[2]) then next end
      stdout=stderr=""
      status = Open4::popen4("./test") do |pid, si, so, se|
        while(line=so.gets) 
          stdout+=line
          puts line
        end
        while(line=se.gets) 
          stderr+=line
          puts line
        end
      end
      if status != 0
        puts "stdout[#{stdout}]"
        puts "stderr[#{stderr}]"
        fail "Running test " + test + " failed."
      end
      if stdout.include?("!!!FAILURES!!!")
        fail "Failures detected running " + test
      end
    end
    cd rootdir
  end
end

task :clean do
  files = Dir.new("./c_files").to_a
  files.each do |dir|
    if dir =~ /^\./ then next end
    draw_line(">",70,dir)
    path = File.join(rootdir,"c_files",dir,"src")
    cd path
    sh "make clean"
    tests = Dir.new(File.join(rootdir,"c_files",dir,"Functions")).to_a
    tests.each do |test|
      if test =~ /^\./ then next end
      draw_line("_",70,dir + "/" + test)
      path = File.join(rootdir,"c_files",dir,"Functions",test)
      cd path
      sh "make clean"
      draw_line("-",70)
    end
    draw_line("<",70)
    cd rootdir
    sh "rm -f runtest"
    sh "rm -f UnitTestEngine/build/*.o"
  end
end

task :clobber => :clean